package com.baomidou.mybatisplus.plugins;

import com.baomidou.mybatisplus.toolkit.PluginUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.type.ObjectTypeHandler;

import java.sql.Connection;
import java.util.*;

/**
 * @Title: DynamicSqlInterceptor
 * @Package com.baomidou.mybatisplus.plugins
 * @Description: 动态sql处理
 * @author Diego jxhjyh123@foxmailcom
 * @date 2018-03-01 15:58
 * @version V1.0
 */
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class DynamicSqlInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object o = invocation.proceed();
        return o;
//        StatementHandler statementHandler = (StatementHandler) PluginUtils.realTarget(invocation.getTarget());
//        MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
//        BoundSql boundSql = (BoundSql) metaObject.getValue("delegate.boundSql");
//        //获取参数信息
//        Object parameterObject = boundSql.getParameterObject();
//        if (parameterObject == null)
//            return invocation.proceed();
//        if (!(parameterObject instanceof DynamicSql))
//            return invocation.proceed();
//        //转换执行对象
//        DynamicSql dynamicSql = (DynamicSql) parameterObject;
//        //参数处理
//        metaObject.setValue("delegate.boundSql.sql", dynamicSql.getOrgSql());
//        metaObject.setValue("delegate.boundSql.parameterMappings", buildParameterMapping(metaObject, dynamicSql));
//        metaObject.setValue("delegate.boundSql.parameterObject", buildParameterObject(dynamicSql));
//        //响应参数类型处理
//        metaObject.getValue("delegate.mappedStatement");
//
//        return invocation.proceed();
    }

    /*
     * @author Diego jxhjyh123@foxmailcom
     * @method
     * @Description 构建参数映射，参数位置与参数名的映射关系
     * @date 2018-03-02 9:22
     * @param null
     * @return
     */
    private List<ParameterMapping> buildParameterMapping(MetaObject metaObject, DynamicSql dynamicSql) {
        Configuration configuration = (Configuration) metaObject.getValue("delegate.configuration");
        if (dynamicSql.getParameters() == null)
            return null;
        List<ParameterMapping> mappingList = new ArrayList<>();
        int i = 1;
        for (Object parameter : dynamicSql.getParameters()) {
            ParameterMapping mapping = new ParameterMapping.Builder(configuration, "param" + i, new ObjectTypeHandler()).javaType(Object.class).mode(ParameterMode.IN).build();
            mappingList.add(mapping);
            i++;
        }
        return mappingList;
    }

    /*
     * @author Diego jxhjyh123@foxmailcom
     * @method
     * @Description 构建参数对象
     * @date 2018-03-02 10:19
     * @param null
     * @return
     */
    private Map<String, Object> buildParameterObject(DynamicSql dynamicSql) {
        if (dynamicSql.getParameters() == null)
            return null;
        Map<String, Object> parameterObject = new HashMap<>();
        int i = 1;
        for (Object parameter : dynamicSql.getParameters()) {
            parameterObject.put("param" + i, parameter);
            i++;
        }
        return parameterObject;
    }

    @Override
    public Object plugin(Object target) {
        if (target instanceof StatementHandler) {
            return Plugin.wrap(target, this);
        }
        return target;
    }

    @Override
    public void setProperties(Properties properties) {

    }
}
